package com.longyiqun.apitest;

import com.google.gson.*;
import io.restassured.http.ContentType;
import io.restassured.response.Response;
import org.testng.Assert;
import org.testng.ITestResult;
import org.testng.Reporter;

import java.util.Iterator;
import java.util.Map;

import static io.restassured.RestAssured.given;

/**
 * program: ApiTest
 * package: com.longyiqun.apitest
 * author: 龙轶群
 * create: 2018-04-17 11:53
 **/


// API主方法
public class GetApiResult {

    public static void getWithVerifyMD5(TestCaseEntity c, String env) {
        // 获取Case基本信息
        String isSign = "";
        String caseMethod = c.getMethod();

        if (c.getSignature() != null) {
            isSign = c.getSignature();
        } else {
            isSign = "off";
        }

        // 判断是POST还是GET请求, 如有其它method, 待扩展
        if (caseMethod.toUpperCase().equals("POST")) {

            // 判断是否验签
            if (isSign.equals("on")) {
                PostWithSignature(c, env);
            } else {
                PostWithOutSignature(c, env);
            }

        } else if (caseMethod.toUpperCase().equals("GET")) {

            if (isSign.equals("on")) {
                GetWithSignature(c, env);
            } else {
                GetWithOutSignature(c, env);
            }
        }
    }
    public static void SceneRequest(TestApiEntity c, String env) {

        String caseMethod = c.getMethod();

        if (caseMethod.toUpperCase().equals("POST")) {
            PostScene(c, env);
        }
    }
    public static void PostScene (TestApiEntity c, String env) {
        // 获取Case信息
        String postBody = c.getBody();
        String caseModel = c.getModule();
        String url = TestServer.getURL(caseModel, env) + c.getUrl();
        String shouldBe = c.getShouldbe();
        String loginName = c.getLoginName();
//        // Log输出
//        YLog.RedGreen("***用例名称: ", c.getChinese());
        YLog.Error("URL: " + url);
//        YLog.GreenRed("模块: ", caseModel);

        login login = new login();
        // 获取登录的Token和UID
        int result = login.loginSet(url, postBody,env,caseModel);
        String tokenAnduid = login.loginGet(loginName, env);
//        String tokenAnduid = "token,22";
        if (!tokenAnduid.equals("")) {

            String token = tokenAnduid.split(",")[0];
            String uid = tokenAnduid.split(",")[1];

            // 获取验签后的BODY体
            JsonObject jsonObject = getBodyWithSign(postBody, token, uid);


            Gson gson = new GsonBuilder().setPrettyPrinting().create();
            JsonParser jp = new JsonParser();

            // 获取Request的Json字符串
            JsonElement jeRequest = jp.parse(jsonObject.toString());
            String prettyJsonRequest = gson.toJson(jeRequest);

            try {
                // 获取response
                final Response response = given().contentType(ContentType.JSON).body(jsonObject.toString()).post(url);

                // 获取JSON返回
                JsonElement jeReturn = jp.parse(response.body().asString());
                String prettyJsonReturn = gson.toJson(jeReturn);

                YLog.MagentYellow("入参: \n", prettyJsonRequest);

                // 获取时长
                final long duration = response.time();
                YLog.BlueBlack("用时: ", (Long.toString(duration) + "ms \n"));
                YLog.BlueBlack("url",c.getUrl());
                // 填充报告
                setAttributeToResult(prettyJsonReturn, prettyJsonRequest, c.getName(), c.getChinese(), url, caseModel, shouldBe);

                // 根据验证字段校验返回值
                verifyResult(shouldBe, jeReturn);

            } catch (Exception ex) {

                // 填充报告
                setAttributeToResult("服务器通信错误, 详细信息: " + ex.getMessage(), prettyJsonRequest, c.getName(), c.getChinese(), url, caseModel, shouldBe);
                Assert.fail(ex.getMessage());
            }
        } else {

            // 填充报告
            setAttributeToResult("登录信息有误, 中断请求", c.getBody(), c.getName(), c.getChinese(), url, caseModel, shouldBe);
            Assert.fail("登录信息有误, 中断请求");
        }
    }
    // Post方法, 有验签, 全部按照有登录状态来做
    private static void PostWithSignature (TestCaseEntity c, String env) {
        // 获取Case信息
        String postBody = c.getBody();
        String caseModel = c.getModule();
        String url = TestServer.getURL(caseModel, env) + c.getUrl();
        String shouldBe = c.getShouldbe();

        // Log输出
        YLog.RedGreen("***用例名称: ", c.getChinese());
        YLog.Error("URL: " + url);
        YLog.GreenRed("模块: ", caseModel);


        // 获取登录的Token和UID
        String tokenAnduid = userLoginReturnToken(caseModel, env);

        if (!tokenAnduid.equals("")) {

            String token = tokenAnduid.split(",")[0];
            String uid = tokenAnduid.split(",")[1];

            // 获取验签后的BODY体
            JsonObject jsonObject = getBodyWithSign(postBody, token, uid);


            Gson gson = new GsonBuilder().setPrettyPrinting().create();
            JsonParser jp = new JsonParser();

            // 获取Request的Json字符串
            JsonElement jeRequest = jp.parse(jsonObject.toString());
            String prettyJsonRequest = gson.toJson(jeRequest);

            try {
                // 获取response
                final Response response = given().contentType(ContentType.JSON).body(jsonObject.toString()).post(url);

                // 获取JSON返回
                JsonElement jeReturn = jp.parse(response.body().asString());
                String prettyJsonReturn = gson.toJson(jeReturn);

                YLog.MagentYellow("入参: \n", prettyJsonRequest);
                // YLog.MagentYellow("Return JSON: \n", prettyJsonReturn);

                // 获取时长
                final long duration = response.time();
                YLog.BlueBlack("用时: ", (Long.toString(duration) + "ms \n"));

                // 填充报告
                setAttributeToResult(prettyJsonReturn, prettyJsonRequest, c.getName(), c.getChinese(), url, caseModel, shouldBe);

                // 根据验证字段校验返回值
                verifyResult(shouldBe, jeReturn);

            } catch (Exception ex) {

                // 填充报告
                setAttributeToResult("服务器通信错误, 详细信息: " + ex.getMessage(), prettyJsonRequest, c.getName(), c.getChinese(), url, caseModel, shouldBe);
                Assert.fail(ex.getMessage());
            }
        } else {

            // 填充报告
            setAttributeToResult("登录信息有误, 中断请求", c.getBody(), c.getName(), c.getChinese(), url, caseModel, shouldBe);
            Assert.fail("登录信息有误, 中断请求");
        }
    }

    // Post方法, 无验签
    private static void PostWithOutSignature (TestCaseEntity c, String env) {
        // 获取Case信息
        String postBody = c.getBody();
        String caseModel = c.getModule();
        String url = TestServer.getURL(caseModel, env) + c.getUrl();
        String shouldBe = c.getShouldbe();

        // Log输出
        YLog.RedGreen("***用例名称: ", c.getChinese());
        YLog.Error("URL: " + url);
        YLog.GreenRed("模块: ", caseModel);

        Gson gson = new GsonBuilder().setPrettyPrinting().create();
        JsonParser jp = new JsonParser();

        // 获取Request的Json字符串
        JsonElement jeRequest = jp.parse(postBody);
        String prettyJsonRequest = gson.toJson(jeRequest);

        try {
            // 获取response
            final Response response = given().contentType(ContentType.JSON).body(postBody).post(url);

            // 获取JSON返回
            JsonElement jeReturn = jp.parse(response.body().asString());
            String prettyJsonReturn = gson.toJson(jeReturn);

            YLog.MagentYellow("入参: \n", prettyJsonRequest);
            // YLog.MagentYellow("Return JSON: \n", prettyJsonReturn);

            // 获取时长
            final long duration = response.time();
            YLog.BlueBlack("用时: ", (Long.toString(duration) + "ms \n"));

            // 填充报告
            setAttributeToResult(prettyJsonReturn, prettyJsonRequest, c.getName(), c.getChinese(), url, caseModel, shouldBe);

            // 根据验证字段校验返回值
            verifyResult(shouldBe, jeReturn);
        } catch (Exception ex) {

            // 填充报告
            setAttributeToResult("服务器通信错误, 详细信息: " + ex.getMessage(), prettyJsonRequest, c.getName(), c.getChinese(), url, caseModel, shouldBe);
            Assert.fail("服务器通信错误, 详细信息: " + ex.getMessage());
        }
    }

    // NONE NOW - Get方法, 有验签
    private static void GetWithSignature (TestCaseEntity testCaseEntity, String env) {
        // TODO
    }

    // Get方法, 无验签
    private static void GetWithOutSignature (TestCaseEntity c, String env) {
        // 获取Case信息
        String caseModel = c.getModule();
        String url = TestServer.getURL(caseModel, env) + c.getUrl() + c.getBody();
        String shouldBe = c.getShouldbe();

        // Log输出
        YLog.RedGreen("***用例名称: ", c.getChinese());
        YLog.Error("URL: " + url);
        YLog.GreenRed("模块: ", caseModel);

        try {

            // 获取response
            final Response response = given().get(url);

            // 获取JSON返回
            JsonParser jp = new JsonParser();
            JsonElement jeReturn = jp.parse(response.body().asString());

            // Log
            YLog.MagentYellow("入参: \n", "此方法为GET, 没有Request JSON");
            // YLog.MagentYellow("Return JSON: \n", response.body().asString());

            // 获取时长
            final long duration = response.time();
            YLog.BlueBlack("用时: ", (Long.toString(duration) + "ms \n"));

            // 填充报告
            setAttributeToResult(response.body().asString(), c.getBody(), c.getName(), c.getChinese(), url, caseModel, shouldBe);

            // 根据验证字段校验返回值
            verifyResult(shouldBe, jeReturn);

        } catch (Exception ex) {

            // 异常请求, 如URL的domain不存在
            setAttributeToResult("服务器通信错误, 详细信息: " + ex.getMessage(), c.getBody(), c.getName(), c.getChinese(), url, caseModel, shouldBe);
            Assert.fail("服务器通信错误, 详细信息: " + ex.getMessage());
        }
    }

    // SUPPORT
    private static void setAttributeToResult (String jsonReturn, String parmsIn, String caseName, String chinese, String caseUrl, String caseModule, String verifyString) {
        // 获取测试结果
        ITestResult result = Reporter.getCurrentTestResult();
        // 插入自定义结果, 此处为API返回&参数输入
        result.setAttribute("jsonReturn", jsonReturn);
        result.setAttribute("parmsIn", parmsIn);
        result.setAttribute("caseName", caseName);
        result.setAttribute("chinese", chinese);
        result.setAttribute("caseUrl", caseUrl);
        result.setAttribute("caseModule", caseModule);
        result.setAttribute("verifyString", verifyString);
    }

    private static void verifyResult(String shouldBe, JsonElement jeReturn) {
        JsonParser parser = new JsonParser();
        JsonObject jsonObj = parser.parse(shouldBe).getAsJsonObject();
        Iterator i$ = jsonObj.entrySet().iterator();
        while(i$.hasNext()) {
            Map.Entry entry = (Map.Entry)i$.next();
            String verifyKey = entry.getKey().toString();
            String verifyValueString = entry.getValue().toString();
            JsonObject verifyValueJson = parser.parse(verifyValueString).getAsJsonObject();

            int verifyValueType = verifyValueJson.get("type").getAsInt();
            String verifyValueValue = verifyValueJson.get("value").getAsString();

            // 开始验证
            if (jeReturn.getAsJsonObject().has(verifyKey)) {
                String returnValue = jeReturn.getAsJsonObject().get(verifyKey).toString();

                if (verifyValueType == 1) {
                    Assert.assertEquals(returnValue, verifyValueValue, "返回字段(" + verifyKey + ")的值不等于预计值<br/>");
                } else {
                    Assert.assertTrue(returnValue.contains(verifyValueValue), "返回字段(" + verifyKey + ")中不包含字段: " + verifyValueValue + "<br/>");
                }
            } else {
                Assert.fail("返回值没有这个KEY: " + verifyKey);
            }
        }
    }

    public static String userLoginReturnToken(String model, String env) {
        String CODE_URL;String CODE_BODY;String Login_URL;
        if (model.equals("记返费")){
            CODE_URL = Constants.JFF_Get_CODE_URL;
            CODE_BODY = Constants.JFF_Get_CODE_BODY;
            Login_URL = Constants.JFF_Login_URL;
        }else {
            CODE_URL = Constants.WODA_Get_CODE_URL;
            CODE_BODY = Constants.WODA_Get_CODE_BODY;
            Login_URL = Constants.WODA_Login_URL;
        }

        // 获取Code的URL
        String findCodeURL;
        System.out.println("模块:"+model+"环境"+env);
        findCodeURL = TestServer.getURL(model, env) + CODE_URL;

        System.out.println("请求地址——————"+TestServer.getURL(model, env));
        // 获取真正的BODY体
        JsonObject jsonObjectCode = getBodyWithSign(CODE_BODY, "", "");

        try {
            // 获取response
            final Response response = given().contentType(ContentType.JSON).body(jsonObjectCode.toString()).post(findCodeURL);

            // 获取response中的验证码
            JsonParser jp = new JsonParser();
            JsonElement jeReturn = jp.parse(response.body().asString());
            String CodeAndMobileJson = jeReturn.getAsJsonObject().get("Data").toString();
            String LOGIN_BODY;
            if (model.equals("记返费")){
                LOGIN_BODY = "{\"Mobile\":\"15062201247\",\"VerifyCode\":"+CodeAndMobileJson+"}";
            }else {
                LOGIN_BODY = CodeAndMobileJson;
            }
            // 获取TOKEN的URL
            String getTokenURL = TestServer.getURL(model, env) + Login_URL;

            // 获取真正的BODY体
            JsonObject jsonObjectTokenUID = getBodyWithSign(LOGIN_BODY, "", "");

            // 获取response
            final Response response1 = given().contentType(ContentType.JSON).body(jsonObjectTokenUID.toString()).post(getTokenURL);
            JsonElement jeReturn1 = jp.parse(response1.body().asString());

            // 返回Token和UID
            String Token = jeReturn1.getAsJsonObject().get("Data").getAsJsonObject().get("Token").getAsString();
            String UID;
            if (model.equals("记返费")){
                UID = jeReturn1.getAsJsonObject().get("Data").getAsJsonObject().get("UserID").toString();
            }else {
                 UID = jeReturn1.getAsJsonObject().get("Data").getAsJsonObject().get("EmployeeID").toString();
            }

            System.out.println("token+++"+Token+"---"+UID);
            return Token + "," + UID;

        } catch (Exception ex) {
            return "";
        }
    }
    public static JsonObject getBodyWithSign(String body, String token, String uid) {
        JsonObject jsonObject = new JsonObject();
        jsonObject.addProperty("AppKey", Constants.WODA_AppKey);
        jsonObject.addProperty("AppVer", Constants.WODA_AppVer);
        jsonObject.addProperty("Data", body);
        jsonObject.addProperty("DeviceName", Constants.WODA_DeviceName);
        jsonObject.addProperty("DeviceType", Constants.WODA_DeviceType);
        jsonObject.addProperty("Lang", Constants.WODA_Lang);

        long time = System.currentTimeMillis();
        String signValue = "WDApp" + time/1000 + "" + body + Constants.MagicKey;

        String signValueMD5 = BussinessUtil.converToMD5(signValue);
        jsonObject.addProperty("Sign", signValueMD5);
        jsonObject.addProperty("Token", token);
        jsonObject.addProperty("Uid", uid);
        jsonObject.addProperty("TimeStamp", time/1000);

        return jsonObject;
    }
}